/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fdcan.h"
#include "i2c.h"
#include "usart.h"
#include "spi.h"
#include "tim.h"
#include "gpio.h"
#include "stm32g4xx_hal.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "stm32g4xx_hal.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lis3mdl_reg.h"
#include "more_printf.h"
// #include "perf_counter.h"
#include "bmi160.h"
#include "bsp_lis3mdl.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
// 定义LED和蜂鸣器的GPIO端口和引脚
#define LED_PIN GPIO_PIN_5
#define LED_GPIO_PORT GPIOA
#define BEEP_PIN GPIO_PIN_0
#define BEEP_GPIO_PORT GPIOB

// 定义440Hz的周期和占空比
#define BEEP_PERIOD 4545  // 440Hz，周期 = 1000000 / 440
#define BEEP_PULSE 2272   // 50%占空比
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define MAX_COMMAND_LENGTH 100
/* USER CODE END PD */
// 串口初始化函数
static void MX_USART1_UART_Init(void) {
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart1);
}

int main(void) {
    // 初始化HAL库
    HAL_Init();
    
    // 配置系统时钟
    SystemClock_Config();
    
    // 初始化GPIO
    MX_GPIO_Init();
    
    // 初始化USART1用于串口通信
    MX_USART1_UART_Init();
    
    // 无限循环，等待输入命令
    while (1) {
        // 打印提示符
        printf("TALOS>> ");
        fflush(stdout);

        // 读取命令
        char command[MAX_COMMAND_LENGTH];
        if (fgets(command, sizeof(command), stdin) == NULL) {
            break;
        }

        // 执行命令
        execute_command(command);
    }

    return 0;
}

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
// LED13对应的GPIO配置
#define LED13_PIN GPIO_PIN_13
#define LED13_GPIO_PORT GPIOC
/* USER CODE END PM */
int main(void)
{
    HAL_Init(); // 初始化HAL库
    LED13_Init(); // 初始化LED13
    MX_USART3_UART_Init(); // 初始化串口3

    while(1)
    {
        // 主循环中无需执行其他操作，所有逻辑在中断中完成
    }
}
/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
struct imu_data_s
{
    float gyro_x;
    float gyro_y;
    float gyro_z;
    float accel_x;
    float accel_y;
    float accel_z;
} imu_data;
uint8_t rx_data;
uint8_t rx_buf[100];
uint8_t rx_length;
uint8_t test_status;
// 定义结构体存储姿态数据

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// 定义延时函数
void delay(uint32_t ms) {
    HAL_Delay(ms);
}

// 初始化LED
void LED_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = LED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
}		
// 初始化蜂鸣器
void BEEP_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = BEEP_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStruct);
}
/*USER CODE END PEP */

/**
  *@brief The application entry point.
  *
  *@retval int
  */
int main(void) {
    HAL_Init();  // 初始化HAL库
    LED_Init();  // 初始化LED
    BEEP_Init(); // 初始化蜂鸣器

    // LED闪烁5次
    LED_Blink(5);

    // 蜂鸣器发声0.5秒
    BEEP_Play();

    // 熄灭LED
    HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN, GPIO_PIN_RESET);

    while (1) {
        // 主循环空闲
    }
		/* USER CODE EMD 2 */
}


// LED闪烁函数
void LED_Blink(uint8_t times) {
    for (uint8_t i = 0; i < times; i++) {
        HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN, GPIO_PIN_SET);
        delay(200);
        HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN, GPIO_PIN_RESET);
        delay(200);
    }
}

// 蜂鸣器发声函数
void BEEP_Play(void) {
    uint32_t start_time = HAL_GetTick();
    while (HAL_GetTick() - start_time < 500) {  // 持续0.5秒
        HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_PIN, GPIO_PIN_SET);
        delay(BEEP_PULSE / 1000);
        HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_PIN, GPIO_PIN_RESET);
        delay((BEEP_PERIOD - BEEP_PULSE) / 1000);
    }
}
void BMI160_euler_test(imu_data_t *imu_data)
{
    bmi160_update(imu_data);
    eular_update(imu_data);
    printf_LPUART("<%d>{euler}%f,%f,%f\r\n", HAL_GetTick(), imu_data->roll, imu_data->pitch, imu_data->yaw);
}
void Magnetometer_test(mag_data_t *mag_data)
{
    lis3mdl_read_data(mag_data);
    printf_LPUART("<%d>{mag}:%f,%f,%f\r\n", HAL_GetTick(), mag_data->mag_x, mag_data->mag_y, mag_data->mag_z);
}
/* USER CODE END PFP */
#define BUFFER_SIZE 10

volatile uint8_t buffer[BUFFER_SIZE];
volatile uint8_t buffer_index = 0;
volatile uint8_t ctrl_c_pressed = 0;
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// USART3中断处理函数
void USART3_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE)) // 检查接收中断标志
    {
        uint8_t received_char = (uint8_t)(huart3.Instance->RDR & (uint8_t)0x00FF); // 读取接收到的字符
        if (received_char == 0x03) // 检测到Ctrl+C (ASCII码为3)
        {
            ctrl_c_pressed = 1;
        }
        else if (buffer_index < BUFFER_SIZE) // 将接收到的字符存储到缓冲区
        {
            buffer[buffer_index++] = received_char;
        }
    }
}

// 模拟程序执行函数
void ProgramExecution(void)
{
    int i = 0;
    while (1)
    {
        if (ctrl_c_pressed) // 检测到Ctrl+C，退出程序
        {
            break;
        }
        HAL_Delay(1000); // 模拟程序执行过程
        i++;
        if (i == 5) // 模拟程序执行完成
        {
            break;
        }
    }
}
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART3_UART_Init();

    __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE); // 使能接收中断
    HAL_NVIC_SetPriority(USART3_IRQn, 5, 0); // 设置中断优先级
    HAL_NVIC_EnableIRQ(USART3_IRQn); // 使能中断

    ProgramExecution(); // 执行程序

    if (ctrl_c_pressed)
    {
        HAL_UART_Transmit(&huart3, (uint8_t*)"Program interrupted by Ctrl+C.\n", 34, HAL_MAX_DELAY);
    }
    else
    {
        HAL_UART_Transmit(&huart3, (uint8_t*)"Program completed successfully.\n", 30, HAL_MAX_DELAY);
    }

    HAL_UART_Transmit(&huart3, (uint8_t*)"TALOS>>", 7, HAL_MAX_DELAY); // 打印提示符

    while (1)
    {
        // 等待用户输入
    }
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
void execute_command(char *command);

int main() {
    char command[MAX_COMMAND_LENGTH];

    while (1) {
        printf("TALOS>> ");
        fflush(stdout);

        if (fgets(command, sizeof(command), stdin) == NULL) {
            break;
        }

        execute_command(command);
    }

    return 0;
}
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_LPUART1_UART_Init();
  MX_I2C1_Init();
  MX_SPI2_Init();
  MX_FDCAN1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&rx_data, 1);
    HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET);
    // HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
    __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3, 2500);
    // w25qxx_test();
    usr_bmi160_init();
    lis3mdl_init(); // 初始化磁力计
    imu_data_t imu_data;
    mag_data_t mag_data; // 存放磁力计数据的位置
    // EulerAngle attitude;
    printf_LPUART("g431 arduino broad test prog\r\n");
    printf_LPUART("输入imu测试陀螺仪，输入mag测试磁力计，输入flash测试flash读取，");
    printf_LPUART("输入buzzer测试蜂鸣器，");
    printf_LPUART("输入euler测试姿态估计，输入q退出测试\r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        switch (test_status)
        {
            case 1:
                bmi160_update(&imu_data);
                printf_LPUART("{gyro}:%f,%f,%f\r\n", imu_data.gyro_x, imu_data.gyro_y, imu_data.gyro_z);
                printf_LPUART("{accel}:%f,%f,%f\r\n", imu_data.accel_x, imu_data.accel_y, imu_data.accel_z);
            break;
            case 2:
                lis3mdl_read_data(&mag_data);
                printf_LPUART("{mag}:%f,%f,%f\r\n", mag_data.mag_x, mag_data.mag_y, mag_data.mag_z);
            break;
            case 3:
                w25qxx_test();
                test_status = 0;
            break;
            case 4:
                BMI160_euler_test(&imu_data);
            break;
            case 5:
                
                HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
                HAL_Delay(500);
                HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_3);
                test_status = 0;
            break;
        }
        HAL_GPIO_TogglePin(LED13_GPIO_Port, LED13_Pin);
        HAL_Delay(50);
    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 85;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV4;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == LPUART1)
    {
        HAL_UART_Transmit(&hlpuart1, &rx_data, 1, 100);
        rx_buf[rx_length++] = rx_data;
        if(rx_data == '\r')
        {
            if(rx_buf[0] == 'i')//陀螺仪测试
            {
                test_status = 1;
                rx_length = 0;
            }
            else if(rx_buf[0] == 'm')//磁力计测试
            {
                test_status = 2;
                rx_length = 0;
            }
            else if(rx_buf[0] == 'f')//flash测试
            {
                test_status = 3;
                rx_length = 0;
            }
            else if (rx_buf[0] == 'e')//姿态测试
            {
                test_status = 4;
                rx_length = 0;
            }
            else if (rx_buf[0] == 'b')//蜂鸣器测试
            {
                test_status = 5;
                rx_length = 0;
            }
            else if(rx_buf[0] == 'q')//退出测试
            {
                test_status = 0;
                rx_length = 0;
            }
            else
            {
                rx_buf[0] = 0x00;
                rx_length = 0;
                rx_data = 0x00;
            }
        }
        HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&rx_data, 1);
    }
}
/* USER CODE END 4 */

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM15 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM15) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */
    __disable_irq();
    while (1)
    {
    }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

